package com.java9s.goldchit.controllers;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.java9s.goldchit.beans.GoldRate;
import com.java9s.goldchit.dao.GoldRateDao;
import com.java9s.goldchit.dao.GoldRateDaoImpl;

@Controller
public class GoldRateController implements ApplicationContextAware {

	private ApplicationContext applicationContext;
	private Validator validator;
	private GoldRateDao goldRateDao;

	public GoldRateDao getGoldRateDao() {
		if (goldRateDao == null) {
			goldRateDao = (GoldRateDaoImpl) applicationContext
					.getBean("goldRateDao");
		}
		return goldRateDao;
	}

	public void setGoldRateDao(GoldRateDao goldRateDao) {
		this.goldRateDao = goldRateDao;
	}

	public GoldRateController() {
		ValidatorFactory validatorFactory = Validation
				.buildDefaultValidatorFactory();
		validator = validatorFactory.getValidator();
	}

	@InitBinder
	protected void initBinder(WebDataBinder binder) {
		SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				dateFormat, false));
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;

	}

	@RequestMapping(value = "updateGoldRate", method = RequestMethod.GET)
	public String updateGoldRate(Model model) {
		GoldRate goldRate = (GoldRate) applicationContext.getBean("goldRate");

		Date today = DateUtils.truncate(new Date(), Calendar.DATE);

		GoldRate todaysRate = getGoldRateDao().getGoldRate(today);
		if (todaysRate == null) {
			todaysRate = goldRate;
			todaysRate.setGoldRateDate(today);
			model.addAttribute("isNewRate", true);
		}
		model.addAttribute("goldRateAttribute", todaysRate);
		return "update-goldrate-tile";
	}

	@RequestMapping(value = "addGoldRate", method = RequestMethod.POST)
	public String addGoldRate(
			@ModelAttribute("goldRateAttribute") GoldRate goldRate,
			BindingResult bindingResult, Model model) {
		beanvalidation(goldRate, bindingResult);
		if (bindingResult.hasErrors()) {
			model.addAttribute("model", model);
		} else {
			getGoldRateDao().saveGoldRate(goldRate);
			model.addAttribute("status", "Gold Rate Added Successfully");
		}
		return "update-goldrate-tile";
	}

	@RequestMapping(value = "updateGoldRate", method = RequestMethod.POST)
	public String updateGoldRate(
			@ModelAttribute("goldRateAttribute") GoldRate goldRate,
			BindingResult bindingResult, Model model) {
		beanvalidation(goldRate, bindingResult);
		if (bindingResult.hasErrors()) {
			model.addAttribute("model", model);
		} else {
			getGoldRateDao().updateGoldRate(goldRate);
			model.addAttribute("status", "Gold Rate Updated Successfully");
		}
		return "update-goldrate-tile";
	}

	private void beanvalidation(GoldRate goldRate, BindingResult bindingResult) {
		Set<ConstraintViolation<GoldRate>> goldRateConstraintViolations = validator
				.validate(goldRate);
		for (ConstraintViolation<GoldRate> constraintViolation : goldRateConstraintViolations) {
			String propertyName = constraintViolation.getPropertyPath()
					.toString();
			String description = constraintViolation.getMessage();
			bindingResult.addError(new FieldError("goldRateAttribute",
					propertyName, description));
		}
	}
}
